package ru.sstu.renju.swing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import java.util.ResourceBundle;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;

import ru.sstu.renju.config.Config;
import ru.sstu.renju.core.Game;
import ru.sstu.renju.core.Move;
import ru.sstu.renju.core.Player;
import ru.sstu.renju.swing.renderers.SwingRenderer;

/**
 * {@code ConfigPanel} class represents main configuration panel.
 *
 * @author denis_murashev
 * @since Renju 1.0
 */
public class ConfigPanel extends JPanel implements Observer {

	private static final long serialVersionUID = -2104598304384953034L;

	private static final int TEXT_FIELD_LENGTH = 5;

	private final Config config;
	private final GamePanel gamePanel;
	private Game game;

	private JComboBox blackPlayer;
	private JComboBox whitePlayer;
	private JComboBox renderer;
	private JTextField delay = new JTextField(TEXT_FIELD_LENGTH);
	private JTextPane log = new JTextPane();
	private JButton playButton;

	/**
	 * Initializes panel.
	 *
	 * @param config    configuration
	 * @param gamePanel Game Panel
	 */
	public ConfigPanel(Config config, GamePanel gamePanel) {
		this.config = config;
		this.gamePanel = gamePanel;
		Player[] players = config.getPlayers().toArray(new Player[0]);
		blackPlayer = new JComboBox(players);
		whitePlayer = new JComboBox(players);
		SwingRenderer[] renderers = config.getRenderers()
				.toArray(new SwingRenderer[0]);
		renderer = new JComboBox(renderers);
		setLayout(new GridBagLayout());
		final int width = 300;
		final int height = config.getGameSize() * config.getCellSize();
		setPreferredSize(new Dimension(width, height));
		GridBagConstraints c = new GridBagConstraints();
		addInputs(c);
		addLogPane(c);
		addButton(c);
	}

	@Override
	public void update(Observable o, Object arg) {
		if (game != null) {
			StringBuilder builder = new StringBuilder();
			int index = 0;
			for (Move move : game.getHistory()) {
				if (index % 2 == 0) {
					builder.append(index / 2 + 1).append(":\t");
					builder.append(move).append("\t");
				} else {
					builder.append(move).append("\n");
				}
				index++;
			}
			log.setText(builder.toString());
			log.setCaretPosition(log.getText().length());
		}
	}

	private void addInputs(GridBagConstraints c) {
		ResourceBundle bundle = config.getBundle();
		final int gap = 5;
		c.insets = new Insets(gap, gap, gap, gap);
		c.anchor = GridBagConstraints.NORTHWEST;
		c.gridx = 0;
		c.gridy = 0;
		add(new JLabel(bundle.getString("config.player.first")), c);
		c.gridx = 1;
		add(blackPlayer, c);
		c.gridx = 0;
		c.gridy++;
		add(new JLabel(bundle.getString("config.player.second")), c);
		c.gridx = 1;
		add(whitePlayer, c);
		c.gridx = 0;
		c.gridy++;
		add(new JLabel(bundle.getString("config.renderer")), c);
		c.gridx = 1;
		add(renderer, c);
		c.gridx = 0;
		c.gridy++;
		add(new JLabel(bundle.getString("config.delay")), c);
		c.gridx = 1;
		add(delay, c);
	}

	private void addLogPane(GridBagConstraints c) {
		c.anchor = GridBagConstraints.CENTER;
		c.fill = GridBagConstraints.BOTH;
		c.gridx = 0;
		c.gridy++;
		c.gridwidth = 2;
		c.weighty = 1.0;
		log.setEditable(false);
		log.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		JScrollPane scrollPane = new JScrollPane(log);
		scrollPane.setHorizontalScrollBarPolicy(JScrollPane
				.HORIZONTAL_SCROLLBAR_NEVER);
		add(scrollPane, c);
	}

	private void addButton(GridBagConstraints c) {
		c.anchor = GridBagConstraints.SOUTH;
		c.fill = GridBagConstraints.NONE;
		c.gridy++;
		c.weighty = 0.0;
		playButton = new JButton(config.getBundle().getString("action.play"));
		add(playButton, c);
		playButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				play();
			}
		});
	}

	/**
	 * Updating the configuration
	 */
	private void updateConfig() {
		config.setBlackPlayer((Player) blackPlayer.getSelectedItem());
		config.setWhitePlayer((Player) whitePlayer.getSelectedItem());
		config.setRenderer((SwingRenderer) renderer.getSelectedItem());
		try {
			config.setMoveDelay(Long.parseLong(delay.getText()));
		} catch (NumberFormatException e) {
			config.setMoveDelay(0);
		}
	}

	/**
	 * Starts playing game.
	 */
	private void play() {
		updateConfig();
		game = new Game(config);
		game.setDelay(config.getMoveDelay());
		gamePanel.setGame(game);
		gamePanel.setRenderer((SwingRenderer) config.getRenderer());
		game.addObserver(this);
		new Thread(game).start();
	}
}
